/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

package treegen;

import java.math.BigDecimal;
import java.text.DecimalFormat;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.event.Event;
import javafx.event.EventHandler;
import javafx.geometry.Insets;
import javafx.scene.control.Button;
import javafx.scene.control.ComboBox;
import javafx.scene.control.ListCell;
import javafx.scene.control.ListView;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.paint.Color;
import javafx.scene.text.Font;
import javafx.scene.text.FontPosture;
import javafx.scene.text.FontWeight;
import javafx.scene.text.Text;
import javafx.util.Callback;
import jfx.messagebox.MessageBox;

/**
 *
 * @author Сергей
 */
public class TrunkPanel {
    
    final TreeGen t;
    
    Callback<ListView<String>, ListCell<String>> factory = new Callback<ListView<String>, ListCell<String>>() {
        @Override
        public ListCell<String> call(ListView<String> list) {
            return new TrunkPanel.ImageCell();
        }
        };
    
    public VBox mainPane = new VBox();
    
    public NumberSpinner widthSpinner = new NumberSpinner(BigDecimal.valueOf(0.00), new BigDecimal("1.00"), new DecimalFormat("#,##0.00"),(float)0.00, (float)1000);
    private HBox width = new HBox();
    
    public NumberSpinner heightSpinner = new NumberSpinner(BigDecimal.valueOf(0.00), new BigDecimal("1.00"), new DecimalFormat("#,##0.00"),(float)0.00, (float)1000.0);
    private HBox height = new HBox();    
    
    public ComboBox comboShape = new ComboBox();
    private HBox shape = new HBox();
    
    public ComboBox comboTrunkCount = new ComboBox();
    private HBox truncCount = new HBox();
    
    public NumberSpinner hStartBranchesSpinner = new NumberSpinner(BigDecimal.valueOf(0.00), new BigDecimal("1.00"), new DecimalFormat("#,##0.00"),(float)0.00, (float)1000.0);
    private HBox hStartBranches = new HBox();
     
    public NumberSpinner divisionCountSpinner = new NumberSpinner((float)0, (float)5);
    private HBox  divisionCount = new HBox();
    
    public NumberSpinner hStartDivisionSpinner = new NumberSpinner(BigDecimal.valueOf(0.00), new BigDecimal("1.00"), new DecimalFormat("#,##0.00"),(float)0.00, (float)1000.0);
    private HBox  hStartDivision = new HBox();
    
    public ComboBox comboTexture = new ComboBox();
    private HBox texture = new HBox();
    
    public ImageView image;
    
    private Text text;
    String strShape = "";
    String strTexture = "";
    
    private HBox reset = new HBox();
    private Button buttonReset = getButton("Сбросить");
    private Button generate ;
    
    //Фактуры коры
    private HBox smooth = new HBox();
    private HBox plastic = new HBox();
    private HBox smallCrack = new HBox();
    private HBox largeCrack = new HBox();
    public HBox imageBox = new HBox();
    
    //Формы ствола
    private HBox vertical = new HBox();
    private HBox sloping = new HBox();
    private HBox curved = new HBox();   
    
    Tree tree;
    
    public TrunkPanel(Tree tree) {
        t = tree.window;
        this.tree = tree;
        
        //=== 1. Ширина ствола ===
        Text widthText = new Text("Ширина ствола:");
        widthText.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        width.getChildren().addAll(widthText, widthSpinner);
        width.setPadding(new Insets(0, 0, 10, 0));      

        
        // === 2. Высота ствола ===
        Text heightText = new Text("Высота ствола:");
        heightText.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        height.getChildren().addAll(heightText, heightSpinner);
        height.setPadding(new Insets(0, 0, 10, 0));

        
        //=== 3. Форма ствола ===
        //прямой ствол
        text = new Text("Прямой");
        text.setFont(Font.font("Verdana", 12));
        vertical.getChildren().addAll(text);
        
        //наклонный ствол
        text = new Text("Наклонный");
        text.setFont(Font.font("Verdana", 12));
        sloping.getChildren().addAll(text);
        
        //изогнутый ствол
        text = new Text("Изогнутый");
        text.setFont(Font.font("Verdana", 12));
        curved.getChildren().addAll(text);
        
        //Комбобокс для формы ствола
        comboShape.getItems().addAll("Прямой", "Наклонный", "Изогнутый");
        Callback<ListView<String>, ListCell<String>> factory = new Callback<ListView<String>, ListCell<String>>() {
        @Override
        public ListCell<String> call(ListView<String> list) {
            return new TrunkPanel.ImageCell();
        }
        };
        comboShape.setCellFactory(factory);
        comboShape.setButtonCell(factory.call(null));

        //Виджет для формы ствола
        text = new Text("Форма ствола: ");
        text.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        shape.getChildren().addAll(text, comboShape);
        shape.setPadding(new Insets(0, 0, 10, 0));
        

        
        comboShape.setValue("Прямой");    
        
        
        //=== 4. Количество стволов ===        
        // Виджет для числа стволов
        Text textTrunckCount = new Text("Количество стволов: ");
        textTrunckCount.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        comboTrunkCount = new ComboBox();
        comboTrunkCount.getItems().addAll(1,2,3,4,5);
        comboTrunkCount.setValue(0);
        
        truncCount.getChildren().addAll(textTrunckCount, comboTrunkCount);
        truncCount.setPadding(new Insets(0, 0, 10, 0));

        comboTrunkCount.setOnAction(new EventHandler() {
        @Override
        public void handle(Event event) {
            changeTrunkCount();
        }
        });
        comboTrunkCount.setValue(1);
        
        //=== 5. Высота начала ветвей ===
        Text hStartBranchesText = new Text("Высота начала ветвей:");
        hStartBranchesText.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        hStartBranches.getChildren().addAll(hStartBranchesText, hStartBranchesSpinner);
        hStartBranches.setPadding(new Insets(0, 0, 10, 0));

        
        //=== 6. Количество разветвлений ===
        Text divisionCountText = new Text("Количество разветвлений:");
        divisionCountText.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        divisionCount.getChildren().addAll(divisionCountText, divisionCountSpinner);
        divisionCount.setPadding(new Insets(0, 0, 10, 0));
        divisionCountSpinner.addSpinnerValueChangedListener(tree.window);
        
        //=== 7. Высота начала разветвлений ===
        Text hStartDivisionText = new Text("Высота начала разветвлений:");
        hStartDivisionText.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        hStartDivision.getChildren().addAll(hStartDivisionText, hStartDivisionSpinner);
        hStartDivision.setPadding(new Insets(0, 0, 10, 0));

        
        //=== 8. Фактура коры ===
        //С гладкой корой
        text = new Text("С гладкой корой");
        text.setFont(Font.font("Verdana", 12));
        smooth.getChildren().addAll(text);
        
        //С пластичной корой
        text = new Text("С пластичной корой");
        text.setFont(Font.font("Verdana", 12));
        plastic.getChildren().addAll(text);
        
        //С мелкотрещиноватой корой
        text = new Text("С мелкотрещиноватой корой");
        text.setFont(Font.font("Verdana", 12));
        smallCrack.getChildren().addAll(text);
        
        //С глубокотрещиноватой корой
        text = new Text("С глубокотрещиноватой корой");
        text.setFont(Font.font("Verdana", 12));
        largeCrack.getChildren().addAll(text);
        
        //Комбобокс для фактуры коры
        comboTexture.getItems().addAll("С гладкой корой","С пластичной корой","С мелкотрещиноватой корой","С глубокотрещиноватой корой");
        comboTexture.getSelectionModel().selectedItemProperty().addListener(
            new ChangeListener() {
            @Override
                public void changed(ObservableValue ov, Object t, Object t1) {
                    build();
                }
            });
        comboTexture.setCellFactory(factory);
        comboTexture.setButtonCell(factory.call(null));
        text = new Text("Фактура коры: ");
        text.setFont(Font.font("Verdana", FontPosture.ITALIC, 14));
        texture.getChildren().addAll(text, comboTexture);
        texture.setPadding(new Insets(0, 0, 10, 0));
        comboTexture.setValue("С гладкой корой");
        
        image = new ImageView(new Image(BranchLevel.class.getResourceAsStream("pictures/smooth.png")));
        imageBox.getChildren().addAll(image);

        
        imageBox.setPadding(new Insets(0, 0, 10, 0));
                          
        //Кнопка "Сбросить"
        text = new Text ("Сбросить");
        text.setFont(Font.font("Verdana", FontWeight.BOLD, 14));
        buttonReset.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                clean();
            }
        });

        reset.getChildren().add(buttonReset);
        reset.setPadding(new Insets(20, 20, 0, 10));

        HBox button1 = new HBox();
        generate = getButton("Сгенерировать");
        generate.addEventHandler(MouseEvent.MOUSE_CLICKED, new EventHandler<MouseEvent>() {
            @Override
            public void handle(MouseEvent mouseEvent) {
                t.cleanCanvas();
                t.getValues();
            }
        });

        button1.getChildren().add(generate);
        button1.setPadding(new Insets(0, 20, 0, 10));
        reset.getChildren().add(button1);
        mainPane.getChildren().addAll( height, width, shape, truncCount, hStartBranches, divisionCount, hStartDivision, texture, imageBox, reset);
        mainPane.setPadding(new Insets(5, 0, 5, 10));

    }
    
    public void changeTrunkCount() {
        int newvalue = getTruncCount();
        if (tree.trunks.size() < newvalue) {           
            int addCount = newvalue -tree.trunks.size();
            for (int i = 0; i < addCount; i++) {
                tree.trunks.add(new Trunk(t.trunkPanel, tree));
            }
        } else if (tree.trunks.size() > newvalue) {
            int delCount = tree.trunks.size() - newvalue ;
            for (int i = 0; i < delCount; i++) {
                tree.trunks.remove(tree.trunks.size() - 1);
            }
        }
    }
    
    /** 
     * Получить кнопку в нужном стиле
     * @param text текст кнопки
     * @return кнопка
     */
    private Button getButton (String text) {
        Button button = new Button(text);
        button.setStyle("-fx-background-color:grey;");
        button.setTextFill(Color.WHITE);
        button.setFont(Font.font("Verdana", FontWeight.BOLD, 12));
        return button;
    }
    
    public void clean(){
        divisionCountSpinner.setNumber(BigDecimal.ZERO);
        hStartBranchesSpinner.setNumber(BigDecimal.ZERO);
        hStartDivisionSpinner.setNumber(BigDecimal.ZERO);
        heightSpinner.setNumber(BigDecimal.ZERO);
        widthSpinner.setNumber(BigDecimal.ZERO);
        
        comboTexture.setValue("С гладкой корой");
        comboShape.setValue("Прямой");
        comboTrunkCount.setValue(1);
        
        image = new ImageView(new Image(BranchLevel.class.getResourceAsStream("pictures/smooth.png")));
        imageBox.getChildren().clear();
        imageBox.getChildren().addAll(image); 
    }
    
    public void build() {
        int type = comboTexture.getButtonCell().getIndex();
        if (type == 0) {
            image = new ImageView(new Image(BranchLevel.class.getResourceAsStream("pictures/smooth.png")));
            imageBox.getChildren().clear();
            imageBox.getChildren().addAll(image); 
        } else if (type == 1) {
            image = new ImageView(new Image(BranchLevel.class.getResourceAsStream("pictures/plastic.png")));
            imageBox.getChildren().clear();
            imageBox.getChildren().addAll(image); 
        }else if (type == 2){
            image = new ImageView(new Image(BranchLevel.class.getResourceAsStream("pictures/smallCrack.png")));
            imageBox.getChildren().clear();
            imageBox.getChildren().addAll(image); 
        }else if (type == 3){
            image = new ImageView(new Image(BranchLevel.class.getResourceAsStream("pictures/largeCrack.png")));
            imageBox.getChildren().clear();
            imageBox.getChildren().addAll(image); 
        }
    }
    
    public double getWidth(){
       return widthSpinner.getNumber().doubleValue();
    }
    
    public void setWidth(BigDecimal number) {
        widthSpinner.setDefaultNumber(number);
    }
    
    public double getHeight(){
        return heightSpinner.getNumber().doubleValue();    
}
    
    public int getShape(){
        strShape = (String) comboShape.getValue();
        return comboShape.getButtonCell().getIndex();
        
    }
    
    public int getTruncCount(){
        return (int) comboTrunkCount.getValue();
    }
    
    public double getHStartBranches(){
        return hStartBranchesSpinner.getNumber().doubleValue();    
    }
    
    public void setHStartBranches(BigDecimal number){
        hStartBranchesSpinner.setDefaultNumber(number);
    }
    
    public int getDivisionCount(){       
        return divisionCountSpinner.getNumber().intValue();      
    }
    
    public void setHStartDivision(BigDecimal number){
        hStartDivisionSpinner.setDefaultNumber(number);
    }
    
    public double getHStartDivision(){
        return hStartDivisionSpinner.getNumber().doubleValue();
        
    }
    
    public TrunkTexture getTexture(){
        int index = comboTexture.getButtonCell().getIndex();
        strTexture = (String) comboTexture.getValue();
        TrunkTexture result;
        switch (index) {
            case 0: result = TrunkTexture.smooth;
                    break;
            case 1: result = TrunkTexture.plastic;
                    break;
            case 2: result = TrunkTexture.smallCrack;
                    break;
            case 3: result = TrunkTexture.largeCrack;
                    break;
            default: result = null;
                    break;

        }
        return result;
    }
    
    public boolean getValues(Trunk trunk) {
        trunk.height = getHeight();
 
        if (getWidth() > trunk.height*0.05 && getWidth() < trunk.height*0.20){
            trunk.width = getWidth();
            trunk.shape = getShape();
            trunk.strShape = strShape;
    
            trunk.truncCount = getTruncCount();
            trunk.hStartBranches = getHStartBranches();
            if ( trunk.hStartBranches > trunk.height * 0.15 && getHStartBranches()<= trunk.height) {
                trunk.hStartBranches = getHStartBranches();
                if (getHStartDivision() < trunk.hStartBranches) {
                    trunk.hStartDivision = getHStartDivision();
                    trunk.divisionCount = getDivisionCount();

                    trunk.texture = getTexture();
                    trunk.strTexture = strTexture;
                    trunk.isSet = true;
                    return true;
                } else {
                    setHStartDivision(BigDecimal.ZERO);
                    MessageBox.show(tree.window._stage,
                            "\nСтвол должен ветвиться до начала ветвей!",
                            "Ограничения",
                            MessageBox.ICON_ERROR | MessageBox.OK | MessageBox.CANCEL);
                    trunk.isSet = false;
                    return false;
                }

                
            } else {
                setHStartBranches(BigDecimal.ZERO);
                MessageBox.show(tree.window._stage,
                        "\nНачало ветвей должно быть не менее 15% от высоты ствола и не более его высоты!",
                        "Ограничения",
                        MessageBox.ICON_ERROR | MessageBox.OK | MessageBox.CANCEL);
                trunk.isSet = false;
                return false;
            }

            
        }
        else {
             setWidth(new BigDecimal("0.00"));
             MessageBox.show(tree.window._stage,
                            "\nШирина ствола должна быть не более 20%  и не менее 5% от высоты!",
                            "Ограничения",
                            MessageBox.ICON_ERROR | MessageBox.OK | MessageBox.CANCEL);
             trunk.isSet = false;
             return false;
        }
        
         
    }

    private static class ImageCell extends ListCell<String> {
        @Override
        public void updateItem(String item, boolean empty) {
            super.updateItem(item, empty);
            if (item != null) {
                if (item.contains("Прямой")) {
                    HBox vertical = new HBox();
                    Text text = new Text("Прямой");
                    text.setFont(Font.font("Verdana", 12));
                    vertical.getChildren().addAll(text);
                    setGraphic(vertical);
                } else if (item.contains("Наклонный")) {
                    HBox sloping = new HBox();
                    Text text = new Text("Наклонный");
                    text.setFont(Font.font("Verdana", 12));
                    sloping.getChildren().addAll(text);
                    setGraphic(sloping);
                } else if (item.contains("Изогнутый")){
                    HBox curved = new HBox();
                    Text text = new Text("Изогнутый");
                    text.setFont(Font.font("Verdana", 12));
                    curved.getChildren().addAll(text);
                    setGraphic(curved);
                } else if (item.contains("С гладкой корой")) {
                    HBox smooth = new HBox();
                    Text text = new Text("С гладкой корой");
                    text.setFont(Font.font("Verdana", 12));
                    smooth.getChildren().addAll(text);
                    setGraphic(smooth);
                } else if (item.contains("С пластичной корой")) {
                    HBox palastic = new HBox();
                    Text text = new Text("С пластичной корой");
                    text.setFont(Font.font("Verdana", 12));
                    palastic.getChildren().addAll(text);
                    setGraphic(palastic);
                } else if (item.contains("С мелкотрещиноватой корой")) {
                    HBox smallCrack = new HBox();
                    Text text = new Text("С мелкотрещиноватой корой");
                    text.setFont(Font.font("Verdana", 12));
                    smallCrack.getChildren().addAll(text);
                    setGraphic(smallCrack);  
                }else if (item.contains("С глубокотрещиноватой корой")) {
                    HBox largeCrack = new HBox();
                    Text text = new Text("С глубокотрещиноватой корой");
                    text.setFont(Font.font("Verdana", 12));
                    largeCrack.getChildren().addAll(text);
                    setGraphic(largeCrack);  
                }
            }
        }
    }
    
    public String inputError(){
        if (!(getWidth() >= getHeight()*5 && getWidth() <= getHeight()*20)){
            return "ширина ствола должна быть не более 20% и не менее 5% от высоты!";      
        }
        if (getHStartBranches() < getHeight()*15 || getHStartBranches() > getHeight()*100){
             return "высота начала ветвей должна быть не менее 15% от высоты (и не больше высоты)!";
        }
        if (getHStartDivision() > getHStartBranches()){
            return "высота начала разветвлений должна быть не больше высоты начала ветвей";
        }
        
        return null;
    }
    
}
